package sz.com.postoffice.jxyzwgcase.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import sz.com.postoffice.jxyzwgcase.dao.app.SigninRecordDao;
import sz.com.postoffice.jxyzwgcase.dao.master.*;
import sz.com.postoffice.jxyzwgcase.pojo.*;
import sz.com.postoffice.jxyzwgcase.service.StatService;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName ResourcServcieImpl
 * @Deacription 统计数据处理层
 * @Author jmx
 * @Date 2020/11/20 18:00
 * @Version 1.0
 **/
@Service
@Slf4j
public class StatServiceImpl implements StatService {
    @Resource
    private GridModelDao gridModelDao;
    @Resource
    private DailyIncomeSummaryDao dailyIncomeSummaryDao;
    @Resource
    private CustomerDao customerDao;
    @Resource
    private UserAdoDao userAdoDao;
    @Resource
    private SigninRecordDao signinRecordDao;
    @Resource
    private StatDeptDao statDeptDao;

    private static final Map<String, String> cityNameMap;

    static {
        cityNameMap = new HashMap<>();
        cityNameMap.put("360100", "南昌市");
        cityNameMap.put("360200", "景德镇市");
        cityNameMap.put("360300", "萍乡市");
        cityNameMap.put("360400", "九江市");
        cityNameMap.put("360500", "新余市");
        cityNameMap.put("360600", "鹰潭市");
        cityNameMap.put("360700", "赣州市");
        cityNameMap.put("360800", "吉安市");
        cityNameMap.put("360900", "宜春市");
        cityNameMap.put("361000", "抚州市");
        cityNameMap.put("361100", "上饶市");
    }

    @Override
    public List<StatResult> getStatResultByCity(List<String> cityCodes, String startTime,
                                                String endTime, int days) {
        List<StatResult> resultList = new ArrayList<>();
        //1.根据city code 查询营业部
        for (String cityCode : cityCodes) {
            StatDept param = new StatDept();
            param.setCityCode(cityCode);
            List<StatDept> deptList = statDeptDao.findByListEntity(param);
            String cityName = cityNameMap.get(cityCode);
            if (deptList == null || deptList.size() <= 0) {
                StatResult emptyDept = new StatResult();
                emptyDept.setCityName(cityName);
                emptyDept.setDeptName("没有配置需要统计的营业部");
                resultList.add(emptyDept);
                continue;
            }

            //0.总人数 1.打卡数 2.走访数 3.日报数 4.登录数（打卡+日报+资源+走访）5.段道数
            List<Integer> totalList = new ArrayList<>();
            for (int i = 0; i < 6; i++) {
                totalList.add(0);
            }
            for (StatDept statDept : deptList) {
                StatResult result = getStatResult(statDept.getDeptCode(), startTime, endTime, days);
                result.setCityName(cityName);
                result.setDeptName(statDept.getDeptName());
                resultList.add(result);
                totalList.set(0, totalList.get(0) + result.getUserCount());
                totalList.set(1, totalList.get(1) + result.getSignNum());
                totalList.set(2, totalList.get(2) + result.getInterviewNum());
                totalList.set(3, totalList.get(3) + result.getDailySummaryCount());
                totalList.set(4, totalList.get(4) + result.getSummaryUserCount());
                totalList.set(5, totalList.get(5) + result.getSectionCount());
            }
            //计算市总数
            resultList.add(getTotalResult(cityName, totalList, days));
        }
        return resultList;
    }

    private StatResult getStatResult(String deptCode, String startTime,
                                     String endTime, int days) {
        StatResult statResult = new StatResult();
        List<UserAdo> userAdos = getAllUser(deptCode);
        Map<String, String> userMap = new HashMap<>();
        //获取营业部的所有adoId不为空的list
        List<String> userIds = getAllUserIds(userAdos, userMap);
        if (userIds != null && userIds.size() > 0) {
            int sectionCount = getSectionNum(deptCode);
            statResult.setSectionCount(sectionCount);
            List<String> signIds = new ArrayList<>();
            int effectiveSignNum = getEffectiveSign(userIds, signIds, startTime, endTime);
            statResult.setSignNum(effectiveSignNum);
            int userCount = getAllEffectiveUserCount(userAdos);
            statResult.setUserCount(userCount);

            List<String> interviewList = customerDao.getInterviewByUser(userIds, startTime, endTime);
            List<String> enterpriseList = customerDao.getEnterpriseByUser(userIds, startTime, endTime);
            List<String> summaryList = dailyIncomeSummaryDao.getUserListByDeptAndDate(deptCode, startTime, endTime);
            setSummaryUser(summaryList, interviewList, enterpriseList, signIds, userMap, statResult);

            statResult.setSummaryUser(getRate(statResult.getSummaryUserCount(), userCount));
            statResult.setDailySummary(getRate(statResult.getDailySummaryCount(), sectionCount * days));
            statResult.setAttendance(getRate(effectiveSignNum, userCount * days * 2));
        }
        return statResult;
    }

    private StatResult getTotalResult(String cityName, List<Integer> totalList, int days) {
        StatResult statResult = new StatResult();
        statResult.setCityName(cityName);
        statResult.setDeptName("市总计");
        //0.总人数 1.打卡数 2.走访数 3.日报数 4.登录数（打卡+日报+资源+走访）5.段道数
        statResult.setUserCount(totalList.get(0));
        statResult.setSignNum(totalList.get(1));
        statResult.setInterviewNum(totalList.get(2));
        statResult.setDailySummaryCount(totalList.get(3));
        statResult.setSummaryUserCount(totalList.get(4));
        statResult.setSectionCount(totalList.get(5));

        statResult.setAttendance(getRate(statResult.getSignNum(), statResult.getUserCount() * days * 2));
        statResult.setDailySummary(getRate(statResult.getDailySummaryCount(), statResult.getSectionCount() * days));
        statResult.setSummaryUser(getRate(statResult.getSummaryUserCount(), statResult.getUserCount()));
        return statResult;
    }

    private List<UserAdo> getAllUser(String deptCode) {
        UserAdo userAdoTemp = new UserAdo();
        userAdoTemp.setDeptCode(deptCode);
        return userAdoDao.findByListEntity(userAdoTemp);
    }

    private List<String> getAllUserIds(List<UserAdo> userAdoList, Map<String, String> userMap) {
        List<String> userIds = new ArrayList<>();
        if (userAdoList != null) {
            for (UserAdo userAdo : userAdoList) {
                if (StringUtils.isNotEmpty(userAdo.getAdoId())) {
                    userIds.add(userAdo.getAdoId());
                    userMap.put(userAdo.getUserCode(), userAdo.getAdoId());
                }
            }
        }
        return userIds;
    }

    private int getAllEffectiveUserCount(List<UserAdo> userAdoList) {
        int num = 0;
        if (userAdoList != null) {
            for (UserAdo userAdo : userAdoList) {
                if (StringUtils.isEmpty(userAdo.getAdoId())) {
                    continue;
                }
                if ("01".equals(userAdo.getEmpStatus())) {
                    num++;
                }
            }
        }
        return num;
    }

    private double getRate(int divisor, int dividend) {
        if (dividend == 0) {
            return 0.0;
        }
        double result = (double) divisor / dividend;
        if (result > 1) {
            return 1;
        }
        return result;
    }

    private int getSectionNum(String deptCode) {
        GridModel paramModel = new GridModel();
        paramModel.setParentCode(deptCode);
        List<GridModel> list = gridModelDao.findByListEntity(paramModel);
        if (list == null) {
            return 0;
        }
        return list.size();
    }

    /**
     * 设置平台使用人数及走访数日报数 打卡+资源+走访+日报其一即可
     *
     * @param summaryList     日报list
     * @param interviewList   走访list
     * @param enterprinceList 企业建档list
     * @param signIds         打卡List
     * @param userAdoMap      营业部所有员工
     * @param result          统计对象
     */
    private void setSummaryUser(List<String> summaryList, List<String> interviewList, List<String> enterprinceList,
                                List<String> signIds, Map<String, String> userAdoMap, StatResult result) {
        Map<String, String> userMap = new HashMap<>();
        if (summaryList == null) {
            result.setDailySummaryCount(0);
        } else {
            result.setDailySummaryCount(summaryList.size());
            for (String userCode : summaryList) {
                String adoId = userAdoMap.get(userCode);
                if (StringUtils.isNotEmpty(adoId)) {
                    userMap.put(adoId, adoId);
                }
            }
        }
        if (interviewList == null) {
            result.setInterviewNum(0);
        } else {
            result.setInterviewNum(interviewList.size());
            for (String userId : interviewList) {
                if (StringUtils.isNotEmpty(userId)) {
                    userMap.put(userId, userId);
                }
            }
        }
        if (enterprinceList != null) {
            for (String userId : enterprinceList) {
                if (StringUtils.isNotEmpty(userId)) {
                    userMap.put(userId, userId);
                }
            }
        }
        if (signIds != null) {
            for (String userId : signIds) {
                if (StringUtils.isNotEmpty(userId)) {
                    userMap.put(userId, userId);
                }
            }
        }
        result.setSummaryUserCount(userMap.size());
    }

    private int getEffectiveSign(List<String> userIds, List<String> signIds,
                                 String startTime, String endTime) {
        List<SigninRecord> signinRecords = signinRecordDao.getSigninByUserList(userIds, startTime, endTime);
        int effectiveSign = 0;
        long beforeTime = 0L;
        long afterTime = 34200000L;
        for (SigninRecord record : signinRecords) {
            signIds.add(record.getUserId());
            if (record.getFirstTime().getTime() <= beforeTime) {
                effectiveSign++;
            }
            if (record.getLastTime().getTime() >= afterTime) {
                effectiveSign++;
            }
        }
        return effectiveSign;
    }

    private Integer getInterviewNum(List<String> userIds, String startTime, String endTime) {
        return customerDao.getInterviewNumByUser(userIds, startTime, endTime);
    }

    private List<GridModel> getAllDept(String cityCode) {
        String pathCode = "360000," + cityCode;
        GridModel gridModel = new GridModel();
        gridModel.setLevel(4);
        gridModel.setAllParentCode(pathCode);
        return gridModelDao.findByListEntity(gridModel);
    }
}
